/**
 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef _COMPILER_OPTIMIZER_OPTIMIZATIONS_INLINE_CALL_INTRINSICS_H
#define _COMPILER_OPTIMIZER_OPTIMIZATIONS_INLINE_CALL_INTRINSICS_H

#include "optimizer/ir/analysis.h"
#include "optimizer/ir/graph.h"
#include "optimizer/pass.h"
#include "utils/arena_containers.h"

namespace ark::compiler {

// Pass aimed to expand intrinsics into some IR involving CallDynamic,
// and allow calls to be processed in EcmaInlining pass afterwards
// Intrinsics that do not produce calls after inlining should be inlined
// in InlineIntrinsics pass for consistency
class InlineCallIntrinsics : public Optimization {
public:
    explicit InlineCallIntrinsics(Graph *graph) : Optimization(graph), functions_(graph->GetAllocator()->Adapter()) {}

    const char *GetPassName() const override
    {
        return "InlineCallIntrinsics";
    }

    bool RunImpl() override;

    bool IsEnable() const override
    {
        return g_options.IsCompilerEcmaInlineCallIntrinsics();
    }

private:
    bool Expand(IntrinsicInst *inst);
    bool ExpandNewObjDynRange(IntrinsicInst *inst);
    void ExpandNewObjDynDefault(Inst *inst);
    void ExpandNewObjDynFastPath(Inst *inst, RuntimeInterface::NewObjDynInfo info, uintptr_t target);
    Inst *CreateAllocDynObjIntrinsic(Inst *ctor, SaveStateInst *ss, uint32_t pc);
    Inst *NewObjCreateConstructorCall(Inst *origCall, Inst *allocObj, SaveStateInst *ss, uint32_t pc);
    Inst *NewObjFillCallConstructorBlock(InstAppender *appender, Inst *origAlloc, Inst *allocObj, uint32_t pc);
    void NewObjFillSlowPathBlock(InstAppender *appender, Inst *origAlloc);
    void NewObjFillCurrBlock(InstAppender *appender, Inst *allocObj, uint32_t pc);
    Inst *NewObjResolveCtorResult(InstAppender *appender, Inst *origAlloc, Inst *allocObj, Inst *callCtor, uint32_t pc);
    void BuildGuard(Inst *inst, uintptr_t target);

    ArenaVector<uintptr_t> functions_;
};

}  // namespace ark::compiler

#endif  // _COMPILER_OPTIMIZER_OPTIMIZATIONS_INLINE_CALL_INTRINSICS_H
